#!/usr/bin/env python3
"""
GitCode组织项目列表获取工具
将curl命令转换为Python代码并生成DataFrame
"""

import json
import os
import random
from datetime import datetime
from typing import Dict, List

import pandas as pd
import requests
from loguru import logger


class GitCodeReposFetcher:
    """GitCode仓库信息获取器"""

    def __init__(self, access_token: str):
        """
        初始化GitCode API客户端
        
        Args:
            access_token: GitCode访问令牌
        """
        self.access_token = access_token
        self.base_url = "https://api.gitcode.com/api/v5"
        self.session = requests.Session()

        # 设置请求头
        self.session.headers.update({
            'User-Agent': 'GitCode-Python-Client/1.0',
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        })

    def get_org_repos(self, org_name: str, **kwargs) -> Dict:
        """
        获取组织的项目列表
        
        Args:
            org_name: 组织名称
            **kwargs: 其他查询参数
                - type: 仓库类型 (all, owner, public, private, member)
                - sort: 排序方式 (created, updated, pushed, full_name)
                - direction: 排序方向 (asc, desc)
                - per_page: 每页数量 (1-100, 默认30)
                - page: 页码 (默认1)
        
        Returns:
            API响应的JSON数据
        """
        url = f"{self.base_url}/orgs/{org_name}/repos"

        # 动态获取访问令牌以避免API调用限制
        current_token = get_random_access_token()

        # 构建查询参数
        params = {
            'access_token': current_token,
            'type': kwargs.get('type', 'all'),
            'sort': kwargs.get('sort', 'updated'),
            'direction': kwargs.get('direction', 'desc'),
            'per_page': kwargs.get('per_page', 30),
            'page': kwargs.get('page', 1)
        }

        try:
            response = self.session.get(url, params=params)
            response.raise_for_status()  # 抛出HTTP错误
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"请求失败: {e}")
            return None
        except json.JSONDecodeError as e:
            logger.error(f"JSON解析失败: {e}")
            return None

    def repos_to_dataframe(self, repos_data: List[Dict]) -> pd.DataFrame:
        """
        将仓库数据转换为DataFrame
        
        Args:
            repos_data: 仓库数据列表
        
        Returns:
            包含仓库信息的DataFrame
        """
        if not repos_data:
            return pd.DataFrame()

        # 提取关键字段
        processed_data = []
        for repo in repos_data:
            processed_repo = {
                'id': repo.get('id'),
                'name': repo.get('path'),
                'full_name': repo.get('full_name'),
                'description': repo.get('description', ''),
                'private': repo.get('private', False),
                'fork': repo.get('fork', False),
                'html_url': repo.get('html_url'),
                'clone_url': repo.get('clone_url'),
                'ssh_url': repo.get('ssh_url'),
                'language': repo.get('language'),
                'size': repo.get('size', 0),
                'stargazers_count': repo.get('stargazers_count', 0),
                'watchers_count': repo.get('watchers_count', 0),
                'forks_count': repo.get('forks_count', 0),
                'open_issues_count': repo.get('open_issues_count', 0),
                'default_branch': repo.get('default_branch', 'master'),
                'created_at': repo.get('created_at'),
                'updated_at': repo.get('updated_at'),
                'pushed_at': repo.get('pushed_at'),
                'archived': repo.get('archived', False),
                'disabled': repo.get('disabled', False),
                'visibility': repo.get('visibility', 'public'),
                # 所有者信息
                'owner_login': repo.get('owner', {}).get('login'),
                'owner_type': repo.get('owner', {}).get('type'),
                'owner_url': repo.get('owner', {}).get('html_url'),
                # 许可证信息
                'license_name': repo.get('license', {}).get('name') if repo.get('license') else None,
                'license_spdx_id': repo.get('license', {}).get('spdx_id') if repo.get('license') else None,
            }
            processed_data.append(processed_repo)

        df = pd.DataFrame(processed_data)

        # 转换时间字段
        time_columns = ['created_at', 'updated_at', 'pushed_at']
        for col in time_columns:
            if col in df.columns:
                df[col] = pd.to_datetime(df[col], errors='coerce')

        return df

    def get_all_repos_dataframe(self, org_name: str, **kwargs) -> pd.DataFrame:
        """
        获取组织所有仓库并返回DataFrame
        
        Args:
            org_name: 组织名称
            **kwargs: 查询参数
        
        Returns:
            包含所有仓库信息的DataFrame
        """
        all_repos = []
        page = 1
        per_page = kwargs.get('per_page', 100)  # 最大每页数量

        while True:
            try:
                import streamlit as st
                st.write(f"正在获取第 {page} 页数据...")
            except ImportError:
                logger.info(f"正在获取第 {page} 页数据...")

            repos_data = self.get_org_repos(
                org_name,
                page=page,
                per_page=per_page,
                **{k: v for k, v in kwargs.items() if k != 'per_page'}
            )

            if not repos_data or len(repos_data) == 0:
                break

            all_repos.extend(repos_data)

            # 如果返回的数据少于per_page，说明已经是最后一页
            if len(repos_data) < per_page:
                break

            page += 1

        try:
            import streamlit as st
            st.write(f"总共获取到 {len(all_repos)} 个仓库")
        except ImportError:
            logger.info(f"总共获取到 {len(all_repos)} 个仓库")
        return self.repos_to_dataframe(all_repos)


def get_random_access_token():
    """从环境变量中获取随机访问令牌"""
    token_str = os.getenv('GITCODE_ACCESS_TOKEN')
    if not token_str:
        logger.error("请设置环境变量 GITCODE_ACCESS_TOKEN")
        return None

    # 支持逗号分隔的多个令牌
    tokens = [token.strip() for token in token_str.split(',') if token.strip()]
    if not tokens:
        logger.error("GITCODE_ACCESS_TOKEN 格式错误，请提供有效的令牌")
        return None

    # 随机选择一个令牌
    selected_token = random.choice(tokens)
    logger.info(f"已选择令牌（前8位）: {selected_token[:8]}...")
    return selected_token


def main():
    """主函数 - 示例用法"""
    # 配置参数
    ACCESS_TOKEN = get_random_access_token()
    if not ACCESS_TOKEN:
        return None

    ORG_NAME = "dlut-water"

    # 创建客户端
    fetcher = GitCodeReposFetcher(ACCESS_TOKEN)

    logger.info(f"正在获取组织 '{ORG_NAME}' 的项目列表...")

    # 获取所有仓库数据
    df = fetcher.get_all_repos_dataframe(
        ORG_NAME,
        type='all',  # 获取所有类型的仓库
        sort='updated',  # 按更新时间排序
        direction='desc'  # 降序排列
    )

    if df.empty:
        logger.warning("未获取到任何仓库数据")
        return

    # 显示基本信息
    logger.info(f"\n=== 仓库统计信息 ===")
    logger.info(f"总仓库数量: {len(df)}")
    logger.info(f"私有仓库: {df['private'].sum()}")
    logger.info(f"公开仓库: {(~df['private']).sum()}")
    logger.info(f"Fork仓库: {df['fork'].sum()}")
    logger.info(f"原创仓库: {(~df['fork']).sum()}")

    # 显示编程语言分布
    logger.info(f"\n=== 编程语言分布 ===")
    language_counts = df['language'].value_counts().head(10)
    for lang, count in language_counts.items():
        logger.info(f"{lang}: {count}")

    # 显示前10个仓库的基本信息
    logger.info(f"\n=== 前10个仓库 ===")
    display_columns = ['name', 'description', 'language', 'stargazers_count', 'forks_count', 'updated_at']
    logger.info(df[display_columns].head(10).to_string(index=False))

    # 保存到CSV文件
    output_file = f"{ORG_NAME}_repos_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
    df.to_csv(output_file, index=False, encoding='utf-8-sig')
    logger.info(f"\n数据已保存到: {output_file}")

    # 保存到Excel文件
    excel_file = f"{ORG_NAME}_repos_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
    with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:
        df.to_excel(writer, sheet_name='仓库列表', index=False)

        # 创建统计汇总表
        summary_data = {
            '统计项': ['总仓库数', '私有仓库', '公开仓库', 'Fork仓库', '原创仓库', '总Star数', '总Fork数'],
            '数量': [
                len(df),
                df['private'].sum(),
                (~df['private']).sum(),
                df['fork'].sum(),
                (~df['fork']).sum(),
                df['stargazers_count'].sum(),
                df['forks_count'].sum()
            ]
        }
        summary_df = pd.DataFrame(summary_data)
        summary_df.to_excel(writer, sheet_name='统计汇总', index=False)

    logger.info(f"Excel文件已保存到: {excel_file}")

    return df


if __name__ == "__main__":
    # 执行主函数
    repos_df = main()
